package health_system.health_system.repository;


import health_system.health_system.entity.ChatMessage;
import health_system.health_system.entity.ChatRoom;
import health_system.health_system.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
public interface ChatMessageRepository extends JpaRepository<ChatMessage, Long> {
    
    // Find all messages in a chat room
    List<ChatMessage> findByChatRoomOrderByCreatedAtAsc(ChatRoom chatRoom);
    
    // Find messages with pagination
    Page<ChatMessage> findByChatRoomOrderByCreatedAtDesc(ChatRoom chatRoom, Pageable pageable);
    
    // Find undelivered messages for a user
    @Query("SELECT m FROM ChatMessage m JOIN m.chatRoom r JOIN r.participants p " +
           "WHERE p = :user AND m.isDeliveredToServer = false " +
           "ORDER BY m.createdAt DESC")
    List<ChatMessage> findUndeliveredMessagesForUser(@Param("user") User user);
    
    // Find unread messages for a user in a chat room
    @Query("SELECT m FROM ChatMessage m LEFT JOIN m.readStatuses rs " +
           "WHERE m.chatRoom = :chatRoom AND m.sender != :user " +
           "AND (rs.user = :user AND rs.isRead = false)")
    List<ChatMessage> findUnreadMessagesInRoom(@Param("chatRoom") ChatRoom chatRoom, @Param("user") User user);
    
    // Count unread messages for a user
    @Query("SELECT COUNT(m) FROM ChatMessage m LEFT JOIN m.readStatuses rs " +
           "WHERE m.chatRoom = :chatRoom AND m.sender != :user " +
           "AND (rs.user = :user AND rs.isRead = false)")
    Long countUnreadMessagesInRoom(@Param("chatRoom") ChatRoom chatRoom, @Param("user") User user);
    
    // Mark messages as delivered
    @Modifying
    @Query("UPDATE ChatMessage m SET m.isDeliveredToServer = true, m.deliveredAt = CURRENT_TIMESTAMP " +
           "WHERE m.id IN :messageIds")
    void markMessagesAsDelivered(@Param("messageIds") List<Long> messageIds);
    
    // Find messages by type
    List<ChatMessage> findByChatRoomAndMessageTypeOrderByCreatedAtDesc(
            ChatRoom chatRoom, ChatMessage.MessageType messageType);
    
    // Find messages in a time period
    List<ChatMessage> findByChatRoomAndCreatedAtBetweenOrderByCreatedAtAsc(
            ChatRoom chatRoom, LocalDateTime startTime, LocalDateTime endTime);
    
    // Search messages by text content
    @Query("SELECT m FROM ChatMessage m WHERE m.chatRoom = :chatRoom " +
           "AND m.textContent LIKE %:searchTerm% ORDER BY m.createdAt DESC")
    List<ChatMessage> searchMessages(@Param("chatRoom") ChatRoom chatRoom, 
                                    @Param("searchTerm") String searchTerm);
    
    // Find pinned messages
    List<ChatMessage> findByChatRoomAndIsPinnedTrue(ChatRoom chatRoom);
    
    // Mark message as recalled
    @Modifying
    @Query("UPDATE ChatMessage m SET m.isRecalled = true, m.recalledAt = CURRENT_TIMESTAMP " +
           "WHERE m.id = :messageId")
    void recallMessage(@Param("messageId") Long messageId);
    
    // Find all media messages
    @Query("SELECT m FROM ChatMessage m WHERE m.chatRoom = :chatRoom " +
           "AND m.messageType IN ('IMAGE', 'VIDEO', 'AUDIO', 'FILE') " +
           "ORDER BY m.createdAt DESC")
    List<ChatMessage> findAllMediaMessages(@Param("chatRoom") ChatRoom chatRoom);
    
    // Get latest message from each chat room for a user
    @Query("SELECT m FROM ChatMessage m WHERE m.id IN " +
           "(SELECT MAX(m2.id) FROM ChatMessage m2 WHERE m2.chatRoom IN " +
           "(SELECT cr FROM ChatRoom cr JOIN cr.participants p WHERE p = :user)) " +
           "ORDER BY m.createdAt DESC")
    List<ChatMessage> findLatestMessagesForUser(@Param("user") User user);
} 